package com.meeting.meetingroom_api.service.impl;

import com.meeting.meetingroom_api.constants.ErrorMessages;
import com.meeting.meetingroom_api.dto.LoginRequestDto;
import com.meeting.meetingroom_api.dto.UserDto;
import com.meeting.meetingroom_api.dto.UserRegistrationDto;
import com.meeting.meetingroom_api.dto.UserUpdateDto;
import com.meeting.meetingroom_api.entity.User;
import com.meeting.meetingroom_api.enums.AccountStatus;
import com.meeting.meetingroom_api.enums.CustomerApprovalStatus;
import com.meeting.meetingroom_api.enums.UserRole;
import com.meeting.meetingroom_api.repository.UserRepository;
import com.meeting.meetingroom_api.service.UserService;
import jakarta.persistence.EntityNotFoundException; // 确保导入
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder; // 确保导入
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;


// 导入 AuthenticationException 或其子类
import javax.security.sasl.AuthenticationException; // 或者使用 Spring Security 的 AuthenticationException

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    @Transactional
    public UserDto registerUser(UserRegistrationDto registrationDto) {
        if (userRepository.existsByUsername(registrationDto.getUsername())) {
            throw new IllegalArgumentException(String.format(ErrorMessages.USERNAME_ALREADY_EXISTS, registrationDto.getUsername()));
        }

        User user = new User();
        user.setUsername(registrationDto.getUsername());
        user.setFullName(registrationDto.getFullName());
        user.setPasswordHash(passwordEncoder.encode(registrationDto.getPassword())); // 使用 passwordEncoder 加密密码
        user.setRole(registrationDto.getRole()); // Set role from DTO

        if (UserRole.customer.equals(registrationDto.getRole())) {
            user.setCompanyName(registrationDto.getCompanyName());
            user.setPhoneNumber(registrationDto.getPhoneNumber());
            user.setAccountStatus(AccountStatus.pending_approval); // Customers need approval
            user.setCustomerApprovalStatus(CustomerApprovalStatus.pending);
        } else if (UserRole.employee.equals(registrationDto.getRole())) {
            // 员工也需要管理员审核
            user.setAccountStatus(AccountStatus.pending_approval); // Employees need approval too
        } else {
            // 只有管理员创建的管理员账户默认激活
            user.setAccountStatus(AccountStatus.active); // Admins are active by default
        }
        User savedUser = userRepository.save(user);
        return convertToDto(savedUser);
    }

    @Override
    @Transactional(readOnly = true) // 登录操作通常是只读的，除非需要更新登录时间等信息
    public UserDto loginUser(LoginRequestDto loginRequestDto) {
        System.out.println("LoginRequestDto: " + loginRequestDto.getUsername() + ", " + loginRequestDto.getPassword());
        User user = userRepository.findByUsername(loginRequestDto.getUsername())
                .orElse(null); // 如果用户不存在，user 为 null
        System.out.println("LoginRequestDto: " + loginRequestDto.getUsername() + ", " + loginRequestDto.getPassword());
        if (user == null) {
            return null; // 用户不存在
        }
        System.out.println("LoginRequestDto: " + loginRequestDto.getUsername() + ", " + loginRequestDto.getPassword());
        if (!passwordEncoder.matches(loginRequestDto.getPassword(), user.getPasswordHash())) {
            return null; // 密码错误
        }

//        if (user.getAccountStatus() != AccountStatus.ACTIVE) {
//            // 可以考虑返回一个包含具体错误信息的 UserDto，或者根据需求细化错误处理
//            // 例如: UserDto errorDto = new UserDto(); errorDto.setErrorMessage("账户未激活或已被锁定: " + user.getAccountStatus()); return errorDto;
//            // 但为了简单起见，这里也返回 null
//            return null; // 账户未激活或已被锁定
//        }
//
//        if (UserRole.CUSTOMER.equals(user.getRole())) {
//            if (user.getCustomerApprovalStatus() != CustomerApprovalStatus.APPROVED) {
//                // 同上，可以细化错误信息
//                return null; // 客户账户尚未批准
//            }
//        }
        // 登录成功，返回用户信息
        return convertToDto(user);
    }

    @Override
    public Page<UserDto> getPendingCustomers(Pageable pageable) {
        Page<User> pendingCustomers = userRepository.findByRoleAndCustomerApprovalStatus(
                UserRole.customer, CustomerApprovalStatus.pending, pageable);
        return pendingCustomers.map(this::convertToDto);
    }

    @Override
    public List<UserDto> getPendingCustomers() {
        List<User> pendingCustomers = userRepository.findByRoleAndCustomerApprovalStatus(
                UserRole.customer, CustomerApprovalStatus.pending);
        return pendingCustomers.stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }

    
    @Override
    public UserDto getUserById(Integer userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new EntityNotFoundException(String.format(ErrorMessages.USER_NOT_FOUND, userId)));
        return convertToDto(user);
    }

    @Override
    public UserDto getUserByUsername(String username) {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new EntityNotFoundException("User not found with username: " + username));
        return convertToDto(user);
    }

    @Override
    public Page<UserDto> getAllUsers(Pageable pageable) {
        // 过滤掉管理员角色（UserRole.ADMIN），并进行分页
        return userRepository.findByRoleNotAndAccountStatusNot(UserRole.admin,AccountStatus.pending_approval,pageable)
                .map(this::convertToDto);
    }

    @Override
    public Page<UserDto> getUsersByRole(UserRole role, Pageable pageable) {
        // 确保只查询客户或员工角色
        if (role == null) {
            return Page.empty();
        }

        if (role == UserRole.customer) {
            // 客户角色：必须过滤 pending_approval 状态
            return userRepository.findByRoleAndAccountStatusNot(
                            role,
                            AccountStatus.pending_approval,
                            pageable
                    )
                    .map(this::convertToDto);
        } else if (role == UserRole.employee) {
            // 员工角色：过滤 pending_approval 状态，只显示已审核的员工
            return userRepository.findByRoleAndAccountStatusNot(
                            role,
                            AccountStatus.pending_approval,
                            pageable
                    )
                    .map(this::convertToDto);
        } else {
            // 其他角色（如管理员）不允许查询
            return Page.empty();
        }
    }
    
    @Override
    @Transactional
    public UserDto updateUser(Integer userId, UserUpdateDto userUpdateDto, Integer adminIdIfApproval) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new EntityNotFoundException("User not found with ID: " + userId));

        if (userUpdateDto.getFullName() != null) {
            user.setFullName(userUpdateDto.getFullName());
        }
        if (userUpdateDto.getPassword() != null && !userUpdateDto.getPassword().isEmpty()) {
            user.setPasswordHash(passwordEncoder.encode(userUpdateDto.getPassword())); // 使用 passwordEncoder 加密新密码
        }
        if (userUpdateDto.getRole() != null) {
            // Add role change authorization logic if needed
            user.setRole(userUpdateDto.getRole());
        }
        if (userUpdateDto.getCompanyName() != null) {
            user.setCompanyName(userUpdateDto.getCompanyName());
        }
        if (userUpdateDto.getPhoneNumber() != null) {
            user.setPhoneNumber(userUpdateDto.getPhoneNumber());
        }
        
        // Admin specific updates for customer
        if (user.getRole() == UserRole.customer) {
            if (userUpdateDto.getCustomerApprovalStatus() != null && adminIdIfApproval != null) {
                 User admin = userRepository.findById(adminIdIfApproval)
                    .orElseThrow(() -> new EntityNotFoundException("Approving admin not found with ID: " + adminIdIfApproval));
                if(admin.getRole() != UserRole.admin){
                    throw new IllegalArgumentException(ErrorMessages.ONLY_ADMINS_CAN_APPROVE_CUSTOMERS);
                }
                user.setCustomerApprovalStatus(userUpdateDto.getCustomerApprovalStatus());
                if (userUpdateDto.getCustomerApprovalStatus() == CustomerApprovalStatus.approved) {
                    user.setAccountStatus(AccountStatus.active);
                    user.setApprovedAt(LocalDateTime.now());
                    user.setApprovedByAdmin(admin);
                } else if (userUpdateDto.getCustomerApprovalStatus() == CustomerApprovalStatus.rejected) {
                     user.setAccountStatus(AccountStatus.frozen); // Or another appropriate status
                }
            }
        }

        if (userUpdateDto.getAccountStatus() != null) {
             // Add account status change authorization logic if needed (e.g., only admin)
            user.setAccountStatus(userUpdateDto.getAccountStatus());
        }

        User updatedUser = userRepository.save(user);
        return convertToDto(updatedUser);
    }


    @Override
    @Transactional
    public void deleteUser(Integer userId) {
        if (!userRepository.existsById(userId)) {
            throw new EntityNotFoundException(String.format(ErrorMessages.USER_NOT_FOUND, userId));
        }
        // Add business logic before deletion if needed (e.g., check for active bookings)
        userRepository.deleteById(userId);
    }

    @Override
    @Transactional
    public UserDto approveCustomerRegistration(Integer customerId, Integer adminId) {
        User customer = userRepository.findById(customerId)
                .orElseThrow(() -> new EntityNotFoundException("Customer not found with ID: " + customerId));
        User admin = userRepository.findById(adminId)
                .orElseThrow(() -> new EntityNotFoundException("Admin not found with ID: " + adminId));

        if (customer.getRole() != UserRole.customer) {
            throw new IllegalArgumentException(ErrorMessages.USER_NOT_CUSTOMER);
        }
        if (admin.getRole() != UserRole.admin) {
            throw new IllegalArgumentException(ErrorMessages.APPROVER_MUST_BE_ADMIN);
        }

        customer.setCustomerApprovalStatus(CustomerApprovalStatus.approved);
        customer.setAccountStatus(AccountStatus.active);
        customer.setApprovedByAdmin(admin);
        customer.setApprovedAt(LocalDateTime.now());
        
        User updatedCustomer = userRepository.save(customer);
        return convertToDto(updatedCustomer);
    }

    @Override
    @Transactional
    public UserDto changeUserAccountStatus(Integer userId, String newStatusValue, Integer adminId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new EntityNotFoundException("User not found with ID: " + userId));
        User admin = userRepository.findById(adminId)
                .orElseThrow(() -> new EntityNotFoundException("Admin not found with ID: " + adminId));
        
        if (admin.getRole() != UserRole.admin) {
            throw new IllegalArgumentException(ErrorMessages.ONLY_ADMINS_CAN_CHANGE_ACCOUNT_STATUS);
        }

        try {
            //AccountStatus newStatus = AccountStatus.valueOf(newStatusValue.toUpperCase());
            AccountStatus newStatus = AccountStatus.valueOf(newStatusValue);
            user.setAccountStatus(newStatus);
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(String.format(ErrorMessages.INVALID_ACCOUNT_STATUS, newStatusValue));
        }
        
        User updatedUser = userRepository.save(user);
        return convertToDto(updatedUser);
    }

    private UserDto convertToDto(User user) {
        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(user, userDto, "passwordHash"); // Exclude passwordHash
        if (user.getApprovedByAdmin() != null) {
            userDto.setApprovedByAdminId(user.getApprovedByAdmin().getUserId());
            userDto.setApprovedByAdminUsername(user.getApprovedByAdmin().getUsername());
        }
        return userDto;
    }

    @Override
    @Transactional
    public void rejectCustomerRegistration(Integer customerId, Integer adminId, String rejectionReason) {
        User customer = userRepository.findById(customerId)
                .orElseThrow(() -> new EntityNotFoundException("Customer not found with ID: " + customerId));
        User admin = userRepository.findById(adminId)
                .orElseThrow(() -> new EntityNotFoundException("Admin not found with ID: " + adminId));

        if (customer.getRole() != UserRole.customer) {
            throw new IllegalArgumentException(ErrorMessages.USER_NOT_CUSTOMER);
        }
        if (admin.getRole() != UserRole.admin) {
            throw new IllegalArgumentException(ErrorMessages.REVIEWER_MUST_BE_ADMIN);
        }
        if (customer.getCustomerApprovalStatus() != CustomerApprovalStatus.pending) {
            throw new IllegalArgumentException(ErrorMessages.CUSTOMER_REGISTRATION_NOT_PENDING);
        }

        // 拒绝后直接删除用户记录，避免用户名冲突
        userRepository.delete(customer);
    }

    @Override
    public Page<UserDto> getActiveUsers(Pageable pageable) {
        // 获取活跃用户（排除管理员）
        Page<User> activeUsers = userRepository.findByRoleNotAndAccountStatus(
                UserRole.admin, AccountStatus.active, pageable);
        return activeUsers.map(this::convertToDto);
    }

    @Override
    public Page<UserDto> getFrozenUsers(Pageable pageable) {
        // 获取冻结用户（排除管理员）
        Page<User> frozenUsers = userRepository.findByRoleNotAndAccountStatus(
                UserRole.admin, AccountStatus.frozen, pageable);
        return frozenUsers.map(this::convertToDto);
    }

    @Override
    public Page<UserDto> getActiveUsersByRole(UserRole role, Pageable pageable) {
        // 校验角色（不允许查询管理员）
        if (role == UserRole.admin) {
            return Page.empty();
        }
        
        Page<User> activeUsers = userRepository.findByRoleAndAccountStatus(
                role, AccountStatus.active, pageable);
        return activeUsers.map(this::convertToDto);
    }

    @Override
    public Page<UserDto> getFrozenUsersByRole(UserRole role, Pageable pageable) {
        // 校验角色（不允许查询管理员）
        if (role == UserRole.admin) {
            return Page.empty();
        }
        
        Page<User> frozenUsers = userRepository.findByRoleAndAccountStatus(
                role, AccountStatus.frozen, pageable);
        return frozenUsers.map(this::convertToDto);
    }
    
    // ==================== 员工审核相关方法实现 ====================
    
    @Override
    public Page<UserDto> getPendingEmployees(Pageable pageable) {
        Page<User> pendingEmployees = userRepository.findByRoleAndAccountStatus(
                UserRole.employee, AccountStatus.pending_approval, pageable);
        return pendingEmployees.map(this::convertToDto);
    }

    @Override
    public List<UserDto> getPendingEmployees() {
        List<User> pendingEmployees = userRepository.findByRoleAndAccountStatus(
                UserRole.employee, AccountStatus.pending_approval);
        return pendingEmployees.stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional
    public UserDto approveEmployeeRegistration(Integer employeeId, Integer adminId) {
        User employee = userRepository.findById(employeeId)
                .orElseThrow(() -> new EntityNotFoundException("Employee not found with ID: " + employeeId));
        User admin = userRepository.findById(adminId)
                .orElseThrow(() -> new EntityNotFoundException("Admin not found with ID: " + adminId));

        if (employee.getRole() != UserRole.employee) {
            throw new IllegalArgumentException(ErrorMessages.USER_NOT_EMPLOYEE);
        }
        if (admin.getRole() != UserRole.admin) {
            throw new IllegalArgumentException(ErrorMessages.APPROVER_MUST_BE_ADMIN);
        }
        if (employee.getAccountStatus() != AccountStatus.pending_approval) {
            throw new IllegalArgumentException(ErrorMessages.EMPLOYEE_NOT_PENDING_APPROVAL);
        }

        employee.setAccountStatus(AccountStatus.active);
        employee.setApprovedByAdmin(admin);
        employee.setApprovedAt(LocalDateTime.now());
        
        User updatedEmployee = userRepository.save(employee);
        return convertToDto(updatedEmployee);
    }
    
    @Override
    @Transactional
    public void rejectEmployeeRegistration(Integer employeeId, Integer adminId, String rejectionReason) {
        User employee = userRepository.findById(employeeId)
                .orElseThrow(() -> new EntityNotFoundException("Employee not found with ID: " + employeeId));
        User admin = userRepository.findById(adminId)
                .orElseThrow(() -> new EntityNotFoundException("Admin not found with ID: " + adminId));

        if (employee.getRole() != UserRole.employee) {
            throw new IllegalArgumentException(ErrorMessages.USER_NOT_EMPLOYEE);
        }
        if (admin.getRole() != UserRole.admin) {
            throw new IllegalArgumentException(ErrorMessages.REVIEWER_MUST_BE_ADMIN);
        }
        if (employee.getAccountStatus() != AccountStatus.pending_approval) {
            throw new IllegalArgumentException(ErrorMessages.EMPLOYEE_NOT_PENDING_APPROVAL);
        }

        // 拒绝后直接删除用户记录，避免用户名冲突
        userRepository.delete(employee);
    }
}